package com.tron.dobest.log;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Api(tags = "日志管理")
@RestController
public class ErrorMessageController {


    @ApiOperation(value = "日志查看")
    @GetMapping("/getLog/{level}")
    public Object getLog(@PathVariable String level) {
        final String infoLevel = level.toLowerCase();
        final String logPath = getLogPath(infoLevel);
        final ArrayList<File> files = foreachFile(new File(logPath), e -> e.contains(infoLevel));
        final List<JSONObject> logInfoList = getLogInfo(files);
        final List<JSONObject> timeSort = logInfoList.stream()
                .sorted(Comparator.comparingLong(e->-LocalDateTime.parse(e.getString("time"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toEpochSecond(ZoneOffset.of("+8"))))
                .collect(Collectors.toList());
        return timeSort;
    }

    /**
     * 获取配置文件中设置的日志路径，level为日志路径下的包名名称
     * 举个栗子，配置文件中<property name="log.path" value="/mylogs" />   ；<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
     * 前一个路径代码自动读出，以后一个error的路径就是这里的level
     *
     * @return
     */
    private String getLogPath(String level) {

        //1.创建Reader对象
        SAXReader reader = new SAXReader();
        //2.加载xml
        Document document = null;
        try {
            File file = ResourceUtils.getFile("classpath:logback-spring.xml");
            document = reader.read(file);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        //3.获取根节点
        Element rootElement = document.getRootElement();
        //4.获取配置文件中第一个property节点，####约定第一个节点放日志路径####
        Element property = rootElement.element("property");
        //5.获取配置日志路径
        Attribute attribute = property.attribute("value");

        return attribute.getValue() +"/"+ level.toLowerCase();
    }

    /**
     * 获取日志文件，判断条件可以根据函数接口传入
     *
     * @param dir
     * @return
     */
    public ArrayList<File> foreachFile(File dir, Predicate<String> predicate) {
        final ArrayList<File> files = new ArrayList<>();
        if (!dir.exists() || !dir.isDirectory()) {
            return files;
        }
        String[] temFiles = dir.list();
        for (int i = 0; i < temFiles.length; i++) {
            File file = new File(dir, temFiles[i]);
            if (file.isFile()) {
                final String fileName = file.getName();
                if (predicate.test(fileName)) {
                    files.add(file);
                }
            }

        }
        return files;
    }

    /**
     * 解析日志文件
     *
     * @param files
     * @return
     */
    public List<JSONObject> getLogInfo(ArrayList<File> files) {
        final ArrayList<JSONObject> arrayList = new ArrayList<>();
        for (File file : files) {
            try (FileReader fileReader = new FileReader(file);
                 BufferedReader bufferedReader = new BufferedReader(fileReader)) {
                String s = null;
                while ((s = bufferedReader.readLine()) != null) {
                    JSONObject parseObject = null;
                    try {
                        parseObject = JSONObject.parseObject(s);
                    } catch (Exception e) {
                        //非json格式日志会抛异常，不处理转换异常。
                    }
                    if (null != parseObject) {
                        arrayList.add(parseObject);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return arrayList;
    }
}
